#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
"""闭包易错点"""


def count():
    # fs里最终存的是循环创建未被调用的三个函数f
    fs = []
    for i in range(1, 4):
        # 每次循环都是在创建函数f但并没有调用
        def f():
            return i * i
        # 此时函数f并没有被调用，添加的是函数f本身，不是f的调用结果
        fs.append(f)
        # 也就是说count()得到的返回值是三个函数
    # 循环结束i为3
    return fs


print(count())

#   易错点1
# 运行print(count())你以为会输出[1,4,9]，而实际上打印了由三个函数构成的列表
# 如果要想打印[1,4,9]，应该将fs.append(f)里的f改为f()

#   易错点2
# 如果不改原代码，而是运行以下代码，结果还是1,4,9吗
# 将count()的返回值(三个函数f)分别赋给三个变量
# f1, f2, f3 = count()
# 打印调用三个函数的结果
# print(f1(), f2(), f3())
# 结果为: 9 9 9 而不是：1 4 9
# 原因是循环里i由1增加到3这个过程只创建了三个函数而未立即调用
# 函数f虽然引用了i，但当循环结束i已经变为3，故返回fs时都只会取到i为3
# 综上返回闭包时牢记一点：返回函数不要引用任何循环变量，或者后续会发生变化的变量
# 如果一定要引用循环变量就再创建一个函数，用该函数的参数绑定循环变量当前的值
# 无论该循环变量后续如何更改，已绑定到函数参数的值不变：
# def count():
#     def f(j):
#         def g():
#             return j * j
#
#         return g
#
#     fs = []
#     for i in range(1, 4):
#         # f(i)立刻被执行，因此i的当前值被传入f()
#         fs.append(f(i))
#     # 虽然i的值是变化的，但是i在循环的每个值时传入f(i)被绑定给了j
#     # 故后续j不会受到i的影响
#     return fs
#
#
# print(count())
